package com.tangding.hprose.api.server;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.tangding.common.exception.GException;
import com.tangding.common.holder.SpringContextHolder;
import com.tangding.common.logx.LogHelp;
import com.tangding.common.tools.ErrorConstants;
import com.tangding.common.utils.AES128;
import com.tangding.common.utils.JacksonUtil;
import com.tangding.config.Config;
import com.tangding.hprose.api.HproseBase;
import com.tangding.hprose.api.server.command.Command;
import com.tangding.hprose.api.server.command.Response;
import com.tangding.hprose.api.server.command.impl.HproseRedirect;
import com.tangding.service.dao.user.LoginRepository;

/**
 * @description 
 *
 * @author Ranger
 * @version 2017年11月21日_下午12:45:30
 *
 */
@Component
public class HproseApiAsServer implements HproseBase {
	
	static LoginRepository loginRepository;
	
	@Autowired
	public void setLoginRepository(LoginRepository loginRepository) {
		HproseApiAsServer.loginRepository = loginRepository;
	}
	
	/**
	 * 保持心跳
	 * 
	 * @return
	 */
	public static boolean heartbeat() {
		return true;
	}

	static final List<Serializable> skipCheckList = Lists.asList(String.class, new String[]{"login"});
	
	@SuppressWarnings("unchecked")
	public static Object commonRequest(String cmd, Object... params) {
		try {
			if (Strings.isNullOrEmpty(cmd) || params == null || params.length == 0) {
				Response response = new Response();
				response.setCode(ErrorConstants.ERR_ILLEGAL_REQUEST);
				response.setMsg(ErrorConstants.getDesc(ErrorConstants.ERR_ILLEGAL_REQUEST));
				return response;
			}
			
			if (!skipCheckList.contains(cmd)) {
				//检测合法性
				Map<String, Object> user = (Map<String, Object>) params[params.length - 1];
				if (user == null) {
					Response response = new Response();
					response.setCode(ErrorConstants.ERR_ILLEGAL_REQUEST);
					response.setMsg(ErrorConstants.getDesc(ErrorConstants.ERR_ILLEGAL_REQUEST));
					return response;
				}
				String uid = (String) user.get("uid");
//				String accessToken = (String) user.get("accessToken");
				String seceret = (String) user.get("seceret");
				String resultString = AES128.Decrypt(seceret, Config.AES128_KEY);
				if (Strings.isNullOrEmpty(resultString) || resultString.indexOf("|") == -1 || resultString.split("[|]").length < 2) {
					throw new GException(ErrorConstants.ERR_ILLEGAL_REQUEST);
				}
				String[] cells = resultString.split("[|]");
				String checkUid = cells[0];
				String checkToken = cells[1];
				if (!checkUid.equals(uid)) {
					throw new GException(ErrorConstants.ERR_ILLEGAL_REQUEST);
				}
				
				String loginToken = loginRepository.get(uid);
				if (Strings.isNullOrEmpty(checkToken) || !checkToken.equals(loginToken)) {//登录已经非法
					throw new GException(ErrorConstants.LOGIN_EXPIRE);
				}
				
				String clientSalt = "";
				if (params.length > 1) {
					Object[] checkParams = new Object[params.length - 1];
					System.arraycopy(params, 0, checkParams, 0, checkParams.length);
					clientSalt = JacksonUtil.toJson(checkParams);
				}
				clientSalt += checkToken;
				/*String clientSeceret = (String) user.get("clientSeceret");
				if (!Utils.getMD5(clientSalt).equals(clientSeceret)) {//TODO：需要进行排序再进行MD5
					throw new GException(ErrorConstants.CLIENT_SECERET_ERR);
				}*/
			}
			
			Command command = SpringContextHolder.getBean(cmd);
			if (command == null) {
				command = SpringContextHolder.getBean(cmd.substring(0, 1).toLowerCase() + cmd.substring(1));
			}
			
			if (command == null) {//转发请求
				Object[] newParams = new Object[params.length + 1];
				newParams[0] = cmd;
				System.arraycopy(params, 0, newParams, 1, params.length);
				params = newParams;
				command = SpringContextHolder.getBean(HproseRedirect.class);
			}
			if (command == null){
				Response response = new Response();
				response.setCode(ErrorConstants.ERR_NOT_FOUND_CMD);
				response.setMsg(ErrorConstants.getDesc(ErrorConstants.ERR_NOT_FOUND_CMD));
				return response;
			}
			
			if (!skipCheckList.contains(cmd)) {
				Map<String, Object> user = (Map<String, Object>) params[params.length - 1];
				String uid = (String) user.get("uid");
				
				Class<?> c = command.getClass();
				String[] permissionNeed = null;//执行指定操作需要的权限列表
				if (AopUtils.isAopProxy(command)) {
					c = AopUtils.getTargetClass(command);
				}
				
				if (c == HproseRedirect.class) {
					permissionNeed = Command.redirectCmd2Auth.get(cmd);
				}else {
					permissionNeed = Command.cmd2Auth.get(c);
				}
				
				if (permissionNeed != null && permissionNeed.length > 0) {
					command.hasAuth(uid, permissionNeed);//检查权限
				}
			}
			
			Response result = command.exe(params);
			return result;
		} catch (GException e) {
			LogHelp.doLogAppErr(e);
			Response response = new Response();
			response.setCode(e.getErr());
			response.setMsg(!Strings.isNullOrEmpty(e.getMsg()) ? e.getMsg() : ErrorConstants.getDesc(e.getErr()));
			return response;
		} catch (Exception e) {
			LogHelp.doLogException(e);
			Response response = new Response();
			response.setCode(ErrorConstants.FAIL);
			response.setMsg(ErrorConstants.getDesc(ErrorConstants.FAIL));
			return response;
		}
	}
}
